#pragma once

#include "common.h"

namespace Server
{
    using namespace std;


    const string default_ip = "0.0.0.0";
    const size_t gnum = 1024;

    enum
    {
        USAGE_ERROR = 1,
        SOCKET_ERROR,
        BIND_ERROR,
        OPEN_ERROR
    };

    typedef function<void (const string&, const uint16_t, const string&, const int)> func_t;

    class udpServer
    {
        
    public:
        udpServer(func_t callback, const uint16_t& port, const string& ip = default_ip)
            : _sockfd(-1), _port(port), _ip(ip), _callback(callback)
        {}

        void initServer()
        {
            //创建socket
            _sockfd = socket(AF_INET, SOCK_DGRAM, 0);
            if (_sockfd == -1)
            {
                cerr << "socket error: " << errno << " : " << strerror(errno) << endl;
                exit(SOCKET_ERROR);
            }

            //绑定 port, ip
            struct sockaddr_in local;
            bzero(&local, sizeof(local));
            local.sin_family = AF_INET;
            local.sin_port = htons(_port);
            // local.sin_addr.s_addr = inet_addr(_ip.c_str());
            local.sin_addr.s_addr = INADDR_ANY;

            int bind_ret = bind(_sockfd, (struct sockaddr*)&local, sizeof(local));
            if (bind_ret == -1)
            {
                cerr << "bind error: " << errno << " : " << strerror(errno) << endl;
                exit(BIND_ERROR);
            }

            cout << "socket succue" << endl;
        }

        void start()
        {
            char buffer[gnum];
            while (true)
            {
                struct sockaddr_in client;
                socklen_t len = sizeof(client);

                ssize_t res_ret = recvfrom(_sockfd, buffer, sizeof(buffer) - 1, 0, (struct sockaddr *)&client, &len);
                if (res_ret > 0)
                {
                    buffer[res_ret] = 0;
                    string client_ip = inet_ntoa(client.sin_addr);//获取ip
                    uint16_t client_port = ntohs(client.sin_port);//端口

                    string client_masage = buffer;//客户端发送的消息

                    cout << client_ip << '[' << client_port << "] # " << client_masage << endl;

                    _callback(client_ip, client_port, client_masage, _sockfd);//业务处理
                }
            }
        }

    private:
        int _sockfd;
        uint16_t _port;
        string _ip;
        func_t _callback;
    };
}